package com.runshu.newsmartark.util.y.crashlogcollector;

import android.content.Context;
import android.util.Log;

import androidx.annotation.NonNull;

import com.runshu.newsmartark.util.y.nativelog.NLogUtil;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.LinkedHashMap;
import java.util.Map;

public abstract class AppCrashLog implements Thread.UncaughtExceptionHandler {
    String TAG = "AppCrashLog";
    /**
     * 设备日志信息
     */
    private LinkedHashMap<String, String> crashLogInfos = new LinkedHashMap<String, String>();
    /**
     * 日期格式类型
     */
    private SimpleDateFormat format = null;
    /**
     * 上下文参数
     */
    private Context context;
    /**
     * 在此类初始化的时候在子类中做一些操作
     * 此刻UncaughtExceptionHandler不为空
     */
    public abstract void initParams();
    /**
     * 系统的异常默认类
     */
    private Thread.UncaughtExceptionHandler exceptionHandler;

    public void init(Context context) {

        try {

            this.context = context;

            /**
             * 获取系统异常默认的类
             */
            exceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

            /**
             * 外抛抽象方法给子类，让其做自己的操作；
             */
            initParams();

            /**
             * 绑定当前类，使当前类为异常处理类
             */
            Thread.setDefaultUncaughtExceptionHandler(this);

            Log.e(TAG, "init - ");
        } catch (Exception e) {
            // TODO: handle exception
            Log.e(TAG, "init - "+e.getMessage());
        }
    }

    /**
     * @param ex
     * @return 如果返回false表示此异常不让开发者处理，或者开发者处理失败最后交由系统处理；
     * 返回true则表明由开发者自己处理
     */
    private boolean handlerException(Throwable ex) {

        try {
            //如果异常类为空，那么返回false
            if (ex == null)
                return false;
            /**
             * 做一个Toast提示，这个可以不要
             */
//            new Thread( new Runnable() {
//                @Override
//                public void run() {
//                    // TODO Auto-generated method stub
//                    Looper.prepare();
//                    Toast.makeText( context, "程序异常", Toast.LENGTH_SHORT ).show();
//                    Looper.loop();
//                }
//            } ).start();
//
//            /**
//             * 之后是手机手机设备信息
//             */
//            collectDeviceInfo( context );
            //把崩溃日志保存到文件中
            crashExceptionWriterFile( ex );

            return true;
        } catch (Exception e) {
            // TODO: handle exception
            Log.e( TAG, "handlerException - " + e.getMessage() );
        }
        return false;
    }

    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable ex) {
        try {
            if (!handlerException( ex ) && exceptionHandler != null) {

                this.exceptionHandler.uncaughtException( thread, ex );
            } else {

                /**
                 * 让程序延迟1秒
                 */
                try {
                    Thread.sleep( 1000 );
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                /**
                 * 退出程序
                 */
                android.os.Process.killProcess( android.os.Process.myPid() );
                System.exit( 1 );
            }

        } catch (Exception e) {
            // TODO: handle exception
            Log.e( "APPCrashLog", "uncaughtException - " + e.getMessage() );
        }
    }

    /**
     * 保存崩溃日志到sd中
     * @param ex
     */
    private void crashExceptionWriterFile(Throwable ex) {
        // TODO Auto-generated method stub
        try {

            if(ex == null)
                return ;
            StringBuffer buffer = new StringBuffer();
            if(crashLogInfos != null && crashLogInfos.size()>0) {

                for(Map.Entry<String, String> entry:crashLogInfos.entrySet()) {

                    buffer.append(entry.getKey()+":"+entry.getValue()+"\n");
                }
            }


            /**
             * 获取异常日志信息
             */
            Writer writer = new StringWriter();
            PrintWriter printWriter = new PrintWriter(writer);
            ex.printStackTrace(printWriter);
            Throwable cause = ex.getCause();

            while(cause != null) {
                cause.printStackTrace(printWriter);
                cause = cause.getCause();
            }

            printWriter.close();

            buffer.append("Exception:\n");
            buffer.append(""+writer.toString());

            /**
             * 设置日志的路径与名称
             */

            String timer = ""+ System.currentTimeMillis();

            if(format == null) {
                format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
            }

//            String tm = format.format(new Date());
//            /**
//             * 日志文件名称
//             */
//            String fileName = "crash-"+tm+"-"+timer+".log";
//TODO 写日志
//            exceptionWriterSd(CACHE_LOG, fileName,  buffer.toString());
            NLogUtil.e( NLogUtil.Err_App_Crash,buffer.toString() );
            /**
             * 日志数量的管理
             * 默认值存在10
             */
//            logLimitCount(LIMIT_FILE_COUNT);
        } catch (Exception e) {
            // TODO: handle exception
            Log.e(TAG, "crashExceptionWriterFile - "+e.getMessage());
        }

    }

}
